using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using DG.Tweening;
using Game.Tile;
using HCore.IOC.Beans.Factory.Attribute.Attr;
using HCore.IOC.Context.Event.Attr;
using HCore.Unity.Behaviour;
using HCore.Unity.Core;
using HCore.Unity.Extensions;
using HCore.Unity.Manager;
using HCore.Unity.Manager.Support.Loader;
using HCore.Utility.Task;
using JetBrains.Annotations;
using Session;
using UI.UIGame;
using UI.UIGame.Loading;
using UnityEngine;
using UnityEngine.Networking;
using Debug = UnityEngine.Debug;

namespace Game.Board
{
    public class BoardVisual : SessionHCoreMonoBehaviour<IBoardSession>
    {
        [Autowired] private BoardService aBoardService;
        [Autowired] private PrefabManager aPrefabManager;
        [Autowired] private SessionService aSessionService;
        [Autowired] private TileService aTileService;
        [Autowired] private UIGameService aUIGameService;

        private LoadingVisual mLoadingVisual;

        /// <summary>
        ///     Unity场景中拼图瓷砖的控制器
        /// </summary>
        private TileVisual[,] TileVisuals { get; set; }

        #region Unity Event

        protected override void Awake()
        {
            base.Awake();

            mLoadingVisual = aPrefabManager.LoadPrefabComponent<LoadingVisual>(GameUtils.UIGameCanvas.transform);
            mLoadingVisual.gameObject.SetActive(false);
            aSessionService.AddNewGameStartPostEvent(OnNewGameStartPostEvent);
        }

        #region New Game

        private void OnNewGameStartPostEvent(ISession _)
        {
            Texture2D originalTex = null;

            var taskQueue = new TaskQueue();
            // 添加一个初始化的设置
            taskQueue.AddCoroutineTask(_ =>
            {
                GameManager.DisabledCameraMove();
                mLoadingVisual.gameObject.SetActive(true);
            }, "拼图加载中");
            // 加载拼图资源
            taskQueue.AddCoroutineTask(subTaskExecute =>
            {
                var uri = new Uri(Path.Combine(Session!.JigsawImagePath));
                return ResourceLoader.RequestData(uri, _RequestTexture, new DownloadHandlerTexture(true));

                IEnumerator _RequestTexture(UnityWebRequest request)
                {
                    originalTex = DownloadHandlerTexture.GetContent(request);
                    yield return null;
                }
            }, "加载拼图图片");
            // 初始化拼图板
            taskQueue.AddTasks(_CreateBoard(() => originalTex));
            // 加载完成后的设置
            taskQueue.AddCoroutineTask(_ =>
            {
                mLoadingVisual.gameObject.SetActive(false);
                GameManager.EnableCameraMove();
            }, "完成拼图制作");

            // 开始执行加载任务
            taskQueue.ExecuteAsync(ProcessLoading);
        }

        /// <summary>
        ///     加载框
        /// </summary>
        /// <param name="taskContext"></param>
        private void ProcessLoading(QueueTaskContext taskContext)
        {
            if (taskContext.Key == null) return;
            mLoadingVisual.SetTitle(taskContext.Key);
            mLoadingVisual.SetSubTitle(taskContext is { SubTaskCompletedCount: 0, SubTaskTotal: 0 } ? "" : $"{taskContext.SubTaskCompletedCount}/{taskContext.SubTaskTotal}");
        }

        #endregion

        #endregion

        #region EventListener

        [UsedImplicitly]
        [EventListener(EventExecuteMode.Coroutine)]
        private void OnTileMoveEvent(TileMoveEvent tileMoveEvent)
        {
            StartCoroutine(_TileMoves(tileMoveEvent.TileMoves));
        }

        private IEnumerator _TileMoves(IEnumerable<TileMoveData> tileMoves)
        {
            foreach (var moveData in tileMoves)
            {
                var tileIndex = moveData.TileIndex;
                var trans = TileVisuals[tileIndex.x, tileIndex.y].transform;
                trans.DOKill(); // 先停掉已经存在的已有效果
                trans.DOMove(moveData.EndPosition.ToVector3(trans.position.z), moveData.Duration).SetEase(Ease.OutCubic);
                switch (moveData.DelaySecond)
                {
                    case <= 0:
                        continue;
                    default:
                        yield return new WaitForSeconds(moveData.DelaySecond);
                        break;
                }
            }
        }

        #endregion

        #region Create Bord

        private TaskQueue _CreateBoard(Func<Texture2D> originalTexFunc)
        {
            Debug.Log($"exec: _CreateBoard, ThreadID: {Thread.CurrentThread.ManagedThreadId}");

            var taskQueue = new TaskQueue();

            // 创建 Board 数据
            taskQueue.AddTasks(Session!.CreateBoard(originalTexFunc));
            // 创建 Board 结束后的处理逻辑
            taskQueue.AddCoroutineTask(_CreateBoardPost, "打乱拼图块");
            return taskQueue;
        }

        private IEnumerator _CreateBoardPost(Action<int, int> subTaskExecute)
        {
            // 创建基础拼图面板，里面有一个透明的拼图精灵和一个不透明的拼图精灵
            Debug.Log("创建基础拼图面板");
            yield return CreateBaseBoard();

            // 创建拼图块
            Debug.Log("创建拼图块");
            yield return _CreateTileVisuals(subTaskExecute);

            // 设置相机位置
            Debug.Log("设置相机位置");
            SetCameraPosition();
            yield return null;

            // 打乱拼图块
            Debug.Log("打乱拼图块");
            aBoardService.SortCenterRandomTiles();
            yield return null;

            // 返回起始点
            Debug.Log("返回起始点");
            aUIGameService.BackToPuzzleStartPoint();
            yield return null;
        }

        private IEnumerator _CreateTileVisuals(Action<int, int> subTaskExecute)
        {
            // 创建一个Tiles父节点
            var tilesGo = new GameObject("Tiles");
            var tileParent = tilesGo.transform;
            tileParent.SetParentAndResetLocalPosition(transform);
            tilesGo.SetActive(false);

            // 创建 TileVisuals
            var board = Session!.Board!;
            var numTileX = board.NumTileX;
            var numTileY = board.NumTileY;
            TileVisuals = new TileVisual[numTileX, numTileY];

            // 准备执行进度数据
            var total = numTileX * numTileY;
            var step = 0;
            subTaskExecute.Invoke(step, total);

            // 填充 TileVisuals
            yield return aTileService.CreateTileVisuals(
                (index, tileVisual) =>
                {
                    if (step++ % 17 == 0) subTaskExecute.Invoke(step, total); // 回调执行进度数据
                    return _CreateTileVisual(index, tileVisual, tileParent);
                },
                index => TileVisuals[index.x, index.y]
            );

            subTaskExecute.Invoke(total, total); // 回调执行进度数据
            yield return null;

            // 等拼图块常见好后，再一起显示透明的拼图底纹
            _TransparentGameObject.gameObject.SetActive(true);
            tilesGo.SetActive(true);
        }

        private IEnumerator _CreateTileVisual(
            Vector2Int index,
            TileVisual tileVisual,
            Transform parent)
        {
            TileVisuals[index.x, index.y] = tileVisual;
            tileVisual.transform.SetParent(parent);
            yield return null;
        }

        /// <summary>
        ///     设置相机的正交尺寸
        /// </summary>
        private void SetCameraPosition()
        {
            var mainCamera = GameUtils.MainCamera;
            var cameraController = mainCamera.GetComponent<CameraControllerBehaviour>();
            var maxSize = cameraController.MouseZoomMax;
            var orthographicSize = Session!.Board!.Sprite.texture.width;

            GameUtils.MainCamera.orthographicSize = Mathf.Min(maxSize, orthographicSize);
        }

        /// <summary>
        ///     保存将显示不透明精灵的GameObject
        /// </summary>
        private GameObject _RealGameObject;

        /// <summary>
        ///     保存显示透明精灵的GameObject。
        /// </summary>
        private GameObject _TransparentGameObject;

        /// <summary>
        ///     创建基础拼图面板，包括了不透明的拼图块，以及透明提示用的拼图底纹。
        /// </summary>
        private IEnumerator CreateBaseBoard()
        {
            ///// 创建不透明精灵，用于显示实际的拼图块。
            _RealGameObject = new GameObject
            {
                name = "RealImage"
            };
            var realSpriteRenderer = _RealGameObject.AddComponent<SpriteRenderer>();
            realSpriteRenderer.sprite = Session!.Board!.Sprite; // 设置精灵图片为拼图块的图片
            realSpriteRenderer.sortingOrder = -10; // 设置渲染顺序，确保不透明拼图块在其他物体之上
            realSpriteRenderer.sortingLayerName = "Real"; // 设置渲染层级
            _RealGameObject.gameObject.SetActive(false); // 默认不激活该物体
            _RealGameObject.transform.SetParent(transform); // 设置父级变换
            yield return null;

            ///// 创建透明精灵，用于显示提示用的拼图底纹。
            _TransparentGameObject = new GameObject
            {
                name = "TransparentImage"
            };
            var transparentSpriteRenderer = _TransparentGameObject.AddComponent<SpriteRenderer>();
            transparentSpriteRenderer.sprite = Session.Board.TransparentSprite; // 设置精灵图片为透明底纹
            transparentSpriteRenderer.sortingOrder = -20; // 设置渲染顺序，确保透明底纹在其他物体之下
            transparentSpriteRenderer.sortingLayerName = "Transparent"; // 设置渲染层级
            _TransparentGameObject.gameObject.SetActive(false); // 默认不激活该物体
            _TransparentGameObject.transform.SetParent(transform); // 设置父级变换
            yield return null;
        }

        #endregion
    }
}